/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * File Name          : freertos.c
 * Description        : Code for freertos applications
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2024 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "queue.h"
#include "bsp_led_driver.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
led_statues led_on_myown(void)
{
    printf("Led is on\r\n");
    HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
    return LED_OK;
}
led_statues led_off_myown(void)
{
    printf("Led is off\r\n");
    HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
    return LED_OK;
}
led_statues led_TogglePin_myown(void)
{
    printf("Led TogglePin\r\n");
    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
    return LED_OK;
}
led_statues led_read_pin_myown(void)
{
    GPIO_PinState bitstatus;
    printf("Led read Pin\r\n");
    bitstatus = HAL_GPIO_ReadPin(LED_GPIO_Port, LED_Pin);
    if (GPIO_PIN_RESET == bitstatus)
    {
        return LED_IS_ON;
    }
    else if (GPIO_PIN_SET == bitstatus)
    {
        return LED_IS_OFF;
    }
    return LED_ERROR;
}
led_operations_t led_operations_myown =
    {
        .pf_led_on = led_on_myown,
        .pf_led_off = led_off_myown,
        .pf_led_TogglePin = led_TogglePin_myown,
        .pf_led_read_pin = led_read_pin_myown};

led_statues get_time_ms_myown(uint32_t *const time_stamp)
{
    printf("get_time_ms\r\n");
    *time_stamp = 0;
    return LED_OK;
}
time_base_ms_t time_base_ms_myown = {.pf_get_time_ms = get_time_ms_myown};

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for LEDTask */
osThreadId_t LEDTaskHandle;
const osThreadAttr_t LEDTask_attributes = {
    .name = "LEDTask",
    .stack_size = 128 * 4,
    .priority = (osPriority_t)osPriorityNormal,
};
/* Definitions for KEYTask */
osThreadId_t KEYTaskHandle;
const osThreadAttr_t KEYTask_attributes = {
    .name = "KEYTask",
    .stack_size = 128 * 4,
    .priority = (osPriority_t)osPriorityLow,
};
/* Definitions for KEY_Queue */
osMessageQueueId_t KEY_QueueHandle;
const osMessageQueueAttr_t KEY_Queue_attributes = {
    .name = "KEY_Queue"};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void Task_LEDFCONTROL(void *argument);
void Task_GETKEY(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
 * @brief  FreeRTOS initialization
 * @param  None
 * @retval None
 */
void MX_FREERTOS_Init(void)
{
    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* USER CODE BEGIN RTOS_MUTEX */
    /* add mutexes, ... */
    /* USER CODE END RTOS_MUTEX */

    /* USER CODE BEGIN RTOS_SEMAPHORES */
    /* add semaphores, ... */
    /* USER CODE END RTOS_SEMAPHORES */

    /* USER CODE BEGIN RTOS_TIMERS */
    /* start timers, add new ones, ... */
    /* USER CODE END RTOS_TIMERS */

    /* Create the queue(s) */
    /* creation of KEY_Queue */
    KEY_QueueHandle = osMessageQueueNew(16, sizeof(uint8_t), &KEY_Queue_attributes);

    /* USER CODE BEGIN RTOS_QUEUES */
    /* add queues, ... */
    /* USER CODE END RTOS_QUEUES */

    /* Create the thread(s) */
    /* creation of LEDTask */
    LEDTaskHandle = osThreadNew(Task_LEDFCONTROL, NULL, &LEDTask_attributes);

    /* creation of KEYTask */
    KEYTaskHandle = osThreadNew(Task_GETKEY, NULL, &KEYTask_attributes);

    /* USER CODE BEGIN RTOS_THREADS */
    /* add threads, ... */
    /* USER CODE END RTOS_THREADS */

    /* USER CODE BEGIN RTOS_EVENTS */
    /* add events, ... */
    /* USER CODE END RTOS_EVENTS */
}

#ifdef OS_SUPPIRTING
led_statues os_delay_ms_myown(const uint32_t ticks)
{
    printf("delay%d\r\n", ticks);
    osDelay(ticks);
    return LED_OK;
}
led_statues os_get_queue_myown(void *const pvBuffer)
{
    if (xQueueReceive(KEY_QueueHandle, pvBuffer, pdMS_TO_TICKS(50)) != pdTRUE)
        return LED_ERROR;
    else
        return LED_OK;
}
os_delay_queue_t os_time_delay_queue_myown = {
    .pf_os_delay_ms = os_delay_ms_myown,
    .pf_os_get_queue = os_get_queue_myown};
#endif

/* USER CODE BEGIN Header_Task_LEDFCONTROL */
/**
 * @brief  Function implementing the LEDTask thread.
 * @param  argument: Not used
 * @retval None
 */
/* USER CODE END Header_Task_LEDFCONTROL */
void Task_LEDFCONTROL(void *argument)
{
    /* USER CODE BEGIN Task_LEDFCONTROL */
    /* Infinite loop */
    bsp_led_driver_t led;
    KEY_RETURN key;
    led_driver_inst(&led, &led_operations_myown, &time_base_ms_myown, &os_time_delay_queue_myown);
    for (;;)
    {
        if (led.p_os_time_delay_queue->pf_os_get_queue(&key) != LED_OK)
            continue;
        // if (xQueueReceive(KEY_QueueHandle, &key, pdMS_TO_TICKS(50)) != pdTRUE)
        //     continue;
        if (key == KEY_ON)
        {
            led.p_led_opes_inst->pf_led_TogglePin();
        }
        // xQueueReceive();
        vTaskDelay(pdMS_TO_TICKS(1000));
        // osDelay(1);
    }
    /* USER CODE END Task_LEDFCONTROL */
}

/* USER CODE BEGIN Header_Task_GETKEY */
/**
 * @brief Function implementing the KEYTask thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_Task_GETKEY */
void Task_GETKEY(void *argument)
{
    /* USER CODE BEGIN Task_GETKEY */
    /* Infinite loop */
    for (;;)
    {
        keyValue = read_key();
        if (KEY_ON == keyValue)
        {
            BaseType_t Return;
            Return = xQueueSendToBack(KEY_QueueHandle, &keyValue, pdMS_TO_TICKS(50));
            //Return = xQueueGenericSend(KEY_QueueHandle, &keyValue, pdMS_TO_TICKS(50), queueSEND_TO_BACK);
            if (errQUEUE_FULL == Return)
            {
                xQueueReset(KEY_QueueHandle);
            }
            vTaskDelay(pdMS_TO_TICKS(300));
        }
        else
        {
            vTaskDelay(pdMS_TO_TICKS(5));
        }
        // osDelay(50);
    }
    /* USER CODE END Task_GETKEY */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */
